# -*- coding: utf-8 -*-
"""
虚拟存储模型
@api-version: 1.0.0
// REF: API-NETDISK-001
"""

from datetime import datetime
from . import db
from enum import IntEnum

class MediaType(IntEnum):
    """媒体类型枚举"""
    DOCUMENT = 1  # 文档
    IMAGE = 2     # 图片
    VIDEO = 3     # 视频
    AUDIO = 4     # 音频
    OTHER = 5     # 其他

class StorageStatus(IntEnum):
    """存储状态枚举"""
    NORMAL = 0    # 正常
    DISABLED = 1  # 禁用

class VirtualStorage(db.Model):
    """虚拟存储核心模型
    
    用于存储文件的元信息和云存储映射关系
    同一个文件（基于MD5）在存储层只保存一份
    """
    __tablename__ = 'virtual_storage'
    
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    file_id = db.Column(db.String(64), unique=True, nullable=False, comment='文件MD5哈希值，作为文件唯一标识')
    original_filename = db.Column(db.String(255), nullable=False, comment='原始文件名（上传时名称）')
    file_size_bytes = db.Column(db.BigInteger, nullable=False, comment='文件大小（字节）')
    media_type = db.Column(db.Integer, nullable=False, default=MediaType.OTHER, comment='媒体类型')
    large_icon_url = db.Column(db.String(500), comment='大缩略图URL')
    small_icon_url = db.Column(db.String(500), comment='小缩略图URL')
    file_extension = db.Column(db.String(20), comment='文件扩展名（小写，不含点）')
    reference_count = db.Column(db.Integer, default=0, comment='引用计数')
    download_count = db.Column(db.Integer, default=0, comment='下载总次数')
    status = db.Column(db.Integer, nullable=False, default=StorageStatus.NORMAL, comment='状态')
    is_hot = db.Column(db.Boolean, default=False, comment='是否热门文件')
    cloud_provider = db.Column(db.String(50), nullable=False, default='tianyi', comment='云存储提供商')
    cloud_file_id = db.Column(db.String(255), nullable=False, comment='云盘文件ID')
    cloud_download_url = db.Column(db.String(1000), comment='云盘下载链接（临时）')
    url_expires_at = db.Column(db.DateTime, comment='下载链接过期时间')
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, comment='创建时间')
    last_modified_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, 
                                onupdate=datetime.utcnow, comment='最后修改时间')
    last_accessed_at = db.Column(db.DateTime, comment='最后访问时间')
    
    # 关联关系
    virtual_files = db.relationship('VirtualFile', backref='storage_file', lazy='dynamic')
    
    def __init__(self, file_id, original_filename, file_size_bytes, cloud_file_id, 
                 cloud_provider='tianyi', media_type=MediaType.OTHER, file_extension=None):
        self.file_id = file_id
        self.original_filename = original_filename
        self.file_size_bytes = file_size_bytes
        self.cloud_file_id = cloud_file_id
        self.cloud_provider = cloud_provider
        self.media_type = media_type
        self.file_extension = file_extension
        self.reference_count = 0
        self.download_count = 0
        self.status = StorageStatus.NORMAL
        self.is_hot = False
    
    def increment_reference(self):
        """增加引用计数"""
        self.reference_count += 1
        db.session.commit()
    
    def decrement_reference(self):
        """减少引用计数"""
        if self.reference_count > 0:
            self.reference_count -= 1
            db.session.commit()
    
    def increment_download(self):
        """增加下载计数"""
        self.download_count += 1
        self.last_accessed_at = datetime.utcnow()
        # 根据下载次数自动标记热门文件
        if self.download_count >= 100:  # 可配置的热门文件阈值
            self.is_hot = True
        db.session.commit()
    
    def update_download_url(self, download_url, expires_at):
        """更新下载链接"""
        self.cloud_download_url = download_url
        self.url_expires_at = expires_at
        db.session.commit()
    
    def is_download_url_valid(self):
        """检查下载链接是否有效"""
        if not self.cloud_download_url or not self.url_expires_at:
            return False
        return datetime.utcnow() < self.url_expires_at
    
    def get_media_type_name(self):
        """获取媒体类型名称"""
        type_names = {
            MediaType.DOCUMENT: '文档',
            MediaType.IMAGE: '图片', 
            MediaType.VIDEO: '视频',
            MediaType.AUDIO: '音频',
            MediaType.OTHER: '其他'
        }
        return type_names.get(self.media_type, '未知')
    
    def get_formatted_size(self):
        """获取格式化的文件大小"""
        size = self.file_size_bytes
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if size < 1024.0:
                return f"{size:.1f} {unit}"
            size /= 1024.0
        return f"{size:.1f} PB"
    
    def can_be_deleted(self):
        """检查是否可以删除（引用计数为0）"""
        return self.reference_count <= 0
    
    def is_active(self):
        """检查是否处于活跃状态"""
        return self.status == StorageStatus.NORMAL
    
    @staticmethod
    def get_media_type_by_extension(extension):
        """根据文件扩展名获取媒体类型"""
        if not extension:
            return MediaType.OTHER
            
        extension = extension.lower().lstrip('.')
        
        # 文档类型
        document_exts = {'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'rtf', 'odt', 'ods', 'odp'}
        if extension in document_exts:
            return MediaType.DOCUMENT
            
        # 图片类型
        image_exts = {'jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp', 'ico', 'tiff', 'tif'}
        if extension in image_exts:
            return MediaType.IMAGE
            
        # 视频类型
        video_exts = {'mp4', 'avi', 'mkv', 'mov', 'wmv', 'flv', 'webm', 'm4v', '3gp', 'rmvb'}
        if extension in video_exts:
            return MediaType.VIDEO
            
        # 音频类型
        audio_exts = {'mp3', 'wav', 'flac', 'aac', 'ogg', 'wma', 'm4a', 'opus'}
        if extension in audio_exts:
            return MediaType.AUDIO
            
        return MediaType.OTHER
    
    def to_dict(self, include_sensitive=False):
        """转换为字典格式"""
        data = {
            'id': self.id,
            'fileId': self.file_id,
            'originalFilename': self.original_filename,
            'fileSizeBytes': self.file_size_bytes,
            'formattedSize': self.get_formatted_size(),
            'mediaType': self.media_type,
            'mediaTypeName': self.get_media_type_name(),
            'fileExtension': self.file_extension,
            'referenceCount': self.reference_count,
            'downloadCount': self.download_count,
            'status': self.status,
            'isHot': self.is_hot,
            'cloudProvider': self.cloud_provider,
            'createdAt': self.created_at.isoformat() if self.created_at else None,
            'lastModifiedAt': self.last_modified_at.isoformat() if self.last_modified_at else None,
            'lastAccessedAt': self.last_accessed_at.isoformat() if self.last_accessed_at else None
        }
        
        # 包含缩略图URL
        if self.large_icon_url:
            data['largeIconUrl'] = self.large_icon_url
        if self.small_icon_url:
            data['smallIconUrl'] = self.small_icon_url
            
        # 敏感信息（仅在需要时包含）
        if include_sensitive:
            data['cloudFileId'] = self.cloud_file_id
            data['cloudDownloadUrl'] = self.cloud_download_url
            data['urlExpiresAt'] = self.url_expires_at.isoformat() if self.url_expires_at else None
            data['isDownloadUrlValid'] = self.is_download_url_valid()
        
        return data
    
    def __repr__(self):
        return f'<VirtualStorage {self.file_id}:{self.original_filename}>'